﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Engine;
using Engine.FileFormats3D.WR2TrafficFiles;
using Engine.Graphics;
using ModelViewer.GraphicObjects;
using SlimDX;

namespace ModelViewer.Tabs
{
    public partial class StreetNodeTab : UserControl, IRenderableObject
    {
        #region Fields (6)

        Engine.Engine engine;
        List<NodeMesh> nodesPosition;
        List<NodeMesh> nodesTangents;
        List<StreetNode> streetNodes;
        List<float> tangentLengths;
        bool updatingControls = false;

        #endregion Fields

        #region Constructors (1)

        public StreetNodeTab()
        {
            InitializeComponent();
            this.streetNodes = new List<StreetNode>();
            this.tangentLengths = new List<float>();
            this.nodesPosition = new List<NodeMesh>();
            this.nodesTangents = new List<NodeMesh>();
        }

        #endregion Constructors

        #region Properties (1)

        public Engine.Engine Engine
        {
            set
            {
                engine = value;
                this.engine.Grafic.RenderableObjects.Add(this);
            }
        }

        #endregion Properties

        #region Methods (6)

        // Private Methods (6) 

        private void AddNewStreetNode(StreetNode streetNode, float tangentLength)
        {
            this.streetNodes.Add(streetNode);
            this.tangentLengths.Add(tangentLength);
            this.listBox_Streetnodes.Items.Add(streetNode);
            this.nodesPosition.Add(new NodeMesh(this.engine.Device, new Vector3(streetNode.positionX, streetNode.positionY, streetNode.positionZ), Color.Red));
            this.nodesTangents.Add(new NodeMesh(this.engine.Device, streetNode.GetPositionFromTangent(tangentLength) + new Vector3(streetNode.positionX, streetNode.positionY, streetNode.positionZ), Color.Blue));
        }

        private void button_AddnewStreetnod_Click(object sender, EventArgs e)
        {
            int index = this.listBox_Streetnodes.Items.Count;
            float x = (float)this.numericUpDown_PositionX.Value;
            float y = (float)this.numericUpDown_PositionY.Value;
            float z = (float)this.numericUpDown_PositionZ.Value;
            float tangentLength = (float)this.numericUpDownTangentLength.Value;
            double angle = (float)this.numericUpDown_Rotation.Value;
            Vector2 rotation = GeoMath.GetVectorFromAngle(angle);
            AddNewStreetNode(new Engine.FileFormats3D.WR2TrafficFiles.StreetNode(index, x, y, z, rotation.X, rotation.Y), tangentLength);
        }

        private void button_RemoveSelectedStreetnode_Click(object sender, EventArgs e)
        {
            ListBox.SelectedIndexCollection collection = this.listBox_Streetnodes.SelectedIndices;
            for (int i = collection.Count - 1; i >= 0; i--)
            {
                RemoveStreetNode(collection[i]);
            }
        }

        private void listBox_Streetnodes_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listBox_Streetnodes.SelectedItems.Count == 1)
            {
                this.updatingControls = true;
                int index = this.listBox_Streetnodes.SelectedIndex;

                this.numericUpDown_PositionX.Value = (decimal)this.streetNodes[index].positionX;
                this.numericUpDown_PositionY.Value = (decimal)this.streetNodes[index].positionY;
                this.numericUpDown_PositionZ.Value = (decimal)this.streetNodes[index].positionZ;
                this.numericUpDown_Rotation.Value = (decimal)this.streetNodes[index].GetDirectionInDegree();
                this.numericUpDownTangentLength.Value = (decimal)this.tangentLengths[index];

                this.updatingControls = false;
            }
        }

        private void OnValueChange(object sender, EventArgs e)
        {
            if (this.numericUpDown_Rotation.Value < 0)
                this.numericUpDown_Rotation.Value += 360;
            if (this.numericUpDown_Rotation.Value >= 360)
                this.numericUpDown_Rotation.Value -= 360;

            if (!this.updatingControls)
            {
                ListBox.SelectedIndexCollection collection = this.listBox_Streetnodes.SelectedIndices;
                for (int i = collection.Count - 1; i >= 0; i--)
                {
                    int index = collection[i];
                    Vector3 position = new Vector3((float)this.numericUpDown_PositionX.Value,
                        (float)this.numericUpDown_PositionY.Value,
                        (float)this.numericUpDown_PositionZ.Value);
                    this.streetNodes[index].positionX = position.X;
                    this.streetNodes[index].positionY = position.Y;
                    this.streetNodes[index].positionZ = position.Z;
                    this.tangentLengths[i] = (float)this.numericUpDownTangentLength.Value;
                    double angle = (float)this.numericUpDown_Rotation.Value;
                    Vector2 rotation = GeoMath.GetVectorFromAngle(angle);
                    this.streetNodes[index].angle1 = rotation.X;
                    this.streetNodes[index].angle2 = rotation.Y;
                    this.nodesPosition[index].UpdatePosition(position);
                    this.nodesTangents[index].UpdatePosition(position + this.streetNodes[index].GetPositionFromTangent(this.tangentLengths[index]));
                }
            }
        }

        private void RemoveStreetNode(int index)
        {
            this.streetNodes.RemoveAt(index);
            this.tangentLengths.RemoveAt(index);
            this.listBox_Streetnodes.Items.RemoveAt(index);
            this.nodesPosition[index].Dispose();
            this.nodesPosition.RemoveAt(index);
            this.nodesTangents[index].Dispose();
            this.nodesTangents.RemoveAt(index);
        }

        #endregion Methods



        #region IRenderableObject Members

        void IRenderableObject.Dispose()
        {
            for (int i = 0; i < this.nodesTangents.Count; i++)
            {
                this.nodesTangents[i].Dispose();
            }
            for (int i = 0; i < this.nodesPosition.Count; i++)
            {
                this.nodesPosition[i].Dispose();
            }
            this.engine.Grafic.RenderableObjects.Remove(this);
        }

        void IRenderableObject.OnDeviceLost()
        {
        }

        void IRenderableObject.OnResetDevice()
        {
        }

        int IRenderableObject.Render()
        {
            for (int i = 0; i < this.streetNodes.Count; i++)
            {
                this.nodesPosition[i].Draw();
                this.nodesTangents[i].Draw();
            }
            return 12;
        }

        #endregion
    }
}
